package com.apes.scm.account.transit;

import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.account.model.DetailOfCustody;
import com.apes.scm.account.account.model.DetailOfUsable;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.stock.model.Location;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 功能：未达账项
 *
 * @author xul
 * @create 2020-02-12 18:45
 */
@Service
public class DepositInTransitService extends DomainService {

    @Autowired
    private DepositInTransitRepository repository;

    public void save(Object entity) {
        DepositInTransit depositInTransit = null;
        if (entity instanceof DetailOfCustody) { /**保管数**/
            DetailOfCustody custody = (DetailOfCustody) entity;
            depositInTransit = findDepositInTransit(custody.getSourceBusinessType(), custody.getOrderNumber(), custody.getOrderSerialNumber(), custody.getLocation());
            if (depositInTransit == null) {
                depositInTransit = new DepositInTransit();
                ReflectUtil.copy(entity, depositInTransit, "company", "sourceBusinessType", "orderNumber", "orderSerialNumber", "location", "product");
                depositInTransit.setCustodyQty(custody.getChangeQty());
            } else {
                depositInTransit.addCustodyQty(custody.getChangeQty());
            }
        } else if (entity instanceof DetailOfUsable) { /**可用数**/
            DetailOfUsable usable = (DetailOfUsable) entity;
            depositInTransit = findDepositInTransit(usable.getSourceBusinessType(), usable.getOrderNumber(), usable.getOrderSerialNumber(), usable.getLocation());
            if (depositInTransit == null) {
                depositInTransit = new DepositInTransit();
                ReflectUtil.copy(entity, depositInTransit, "company", "sourceBusinessType", "orderNumber", "orderSerialNumber", "location", "product");
                depositInTransit.setUsableQty(usable.getChangeQty());
                depositInTransit.setNextOperation("发货");
            } else {
                depositInTransit.addUsableQty(usable.getChangeQty());
            }
            depositInTransit.setOccurQty(usable.getChangeQty());
        } else if (entity instanceof DepositInTransit) {
            depositInTransit = (DepositInTransit) entity;
        }
        if (depositInTransit == null) throw new RuntimeException("未达账数据为空！");
        if (depositInTransit.getId() != null && ((Math.abs(depositInTransit.getOccurQty()) == Math.abs(depositInTransit.getUsableQty()) && Math.abs(depositInTransit.getUsableQty()) == Math.abs(depositInTransit.getCustodyQty())) || (depositInTransit.getUsableQty() == 0 && depositInTransit.getCustodyQty() == 0))) {
            repository.delete(depositInTransit);
        } else {
            repository.saveAndFlush(depositInTransit);
        }
    }

    public void save(PartyRole company, Location location, Dept receivingDept, String sourceBusinessType, String orderNumber, String orderSerialNumber, Product product, double occurQty, String nextOperation) {
        DepositInTransit depositInTransit = findDepositInTransit(sourceBusinessType, orderNumber, orderSerialNumber, location);
        if (depositInTransit == null) {
            depositInTransit = new DepositInTransit();
            depositInTransit.setCompany(company);
            depositInTransit.setLocation(location);
            depositInTransit.setSourceBusinessType(sourceBusinessType);
            depositInTransit.setOrderNumber(orderNumber);
            depositInTransit.setOrderSerialNumber(orderSerialNumber);
            depositInTransit.setProduct(product);
            if (receivingDept != null) depositInTransit.setReceivingDept(receivingDept);
        }
        depositInTransit.setOccurQty(occurQty);
        depositInTransit.setNextOperation(nextOperation);
        save(depositInTransit);
    }

    public void delete(String sourceBusinessType, String orderNumber, String orderSerialNumber, Location location) {
        DepositInTransit depositInTransit = findDepositInTransit(sourceBusinessType, orderNumber, orderSerialNumber, location);
        if (depositInTransit != null) {
            repository.delete(depositInTransit);
        }
    }

    private DepositInTransit findDepositInTransit(String sourceBusinessType, String orderNumber, String orderSerialNumber, Location location) {
        return repository.findOne(JpaDsl.toCriteria(MapUtil.mapper("sourceBusinessType", sourceBusinessType, "orderNumber", orderNumber, "orderSerialNumber", orderSerialNumber, "location", location))).orElse(null);
    }

    /**
     * 未达账分组汇总
     *
     * @param request
     * @return
     */
    public List<Map> groupDepositInTransit(SimpleRequest request) {
        return repository.groupFindAllDepositInTransit();
    }

    /**
     * 获取未达账明细
     *
     * @param request
     * @return
     */
    public JSONObject findDepositInTransitItem(SimpleRequest request) {
        String type = JSONObject.parseObject(request.getData().toString()).getJSONObject("data").getString("SOURCE_BUSINESS_TYPE");
        List<Map> list;
        if (Objects.equals(type, "Total")) {
            list = repository.findBySourceBusinessType();
        } else {
            list = repository.findBySourceBusinessType(type);
        }
        JSONObject object = new JSONObject();
        object.put("content", list);
        return object;
    }

    /**
     * 处理异常未达账明细
     **/
    public void handlingMissing() {
        repository.exec("delete ACC_DEPOSIT_IN_TRANSIT a\n" +
                " where a.order_number in\n" +
                "       (select order_number\n" +
                "          from (select a.order_number, sum(a.custody_qty) custody_qty,\n" +
                "                        sum(a.usable_qty) usable_qty,\n" +
                "                        sum(a.occur_qty) occur_qty\n" +
                "                   from ACC_DEPOSIT_IN_TRANSIT a\n" +
                "                  group by a.order_number\n" +
                "                 having (sum(a.custody_qty) = sum(a.usable_qty) and sum(a.custody_qty) != 0) or\n" +
                "                        (sum(a.custody_qty) != 0 and sum(a.usable_qty) = 0)\n" +
                "                )\n" +
                "        )");
    }
}
